package zcj.stu;

import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.MethodParameter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.annotation.ExpressionValueMethodArgumentResolver;
import org.springframework.web.method.annotation.RequestHeaderMethodArgumentResolver;
import org.springframework.web.method.annotation.RequestParamMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodArgumentResolverComposite;
import org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.mvc.method.annotation.*;

import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;

public class C29 {
    public static void main(String[] args) throws Exception{
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(WebConfig.class);
        MockHttpServletRequest request = new MockHttpServletRequest();
        request.setParameter("name","张三");
        request.setParameter("age","18");
        ServletInvocableHandlerMethod invocableHandlerMethod = new
                ServletInvocableHandlerMethod(context.getBean(WebConfig.Controller1.class),
                WebConfig.Controller1.class.getMethod("testResponseBodyAdvice")
        );
        ServletRequestDataBinderFactory binderFactory = new ServletRequestDataBinderFactory(Collections.emptyList(), null);
        invocableHandlerMethod.setDataBinderFactory(binderFactory);
        invocableHandlerMethod.setParameterNameDiscoverer(new DefaultParameterNameDiscoverer());
        invocableHandlerMethod.setHandlerMethodArgumentResolvers(getComposite(context.getDefaultListableBeanFactory()));
        invocableHandlerMethod.setHandlerMethodReturnValueHandlers(getComposite(context.getDefaultListableBeanFactory(),0));
        ModelAndViewContainer container = new ModelAndViewContainer();

        MockHttpServletResponse response = new MockHttpServletResponse();
        invocableHandlerMethod.invokeAndHandle(new ServletWebRequest(request,response),container);
        MethodParameter[] parameters = invocableHandlerMethod.getMethodParameters();
        for (MethodParameter parameter : parameters) {
            System.out.println(parameter.getParameterName());
        }
        System.out.println(new String(response.getContentAsByteArray(),StandardCharsets.UTF_8));
        context.close();

    }
    public static HandlerMethodArgumentResolverComposite getComposite(ConfigurableBeanFactory beanFactory){

        HandlerMethodArgumentResolverComposite composite = new HandlerMethodArgumentResolverComposite();
        composite.addResolvers(
                new RequestParamMethodArgumentResolver(beanFactory,false),
                new PathVariableMethodArgumentResolver(),
                new RequestHeaderMethodArgumentResolver(beanFactory),
                new ServletCookieValueMethodArgumentResolver(beanFactory),
                new ExpressionValueMethodArgumentResolver(beanFactory),
                new ServletRequestMethodArgumentResolver(),
                new ServletModelAttributeMethodProcessor(false),
                new RequestResponseBodyMethodProcessor(List.of(new MappingJackson2HttpMessageConverter())),
                new ServletModelAttributeMethodProcessor(true),
                new RequestParamMethodArgumentResolver(beanFactory,true)
        );
        return  composite;
    }
    public static HandlerMethodReturnValueHandlerComposite getComposite(ConfigurableBeanFactory beanFactory,int p){

        HandlerMethodReturnValueHandlerComposite composite=new HandlerMethodReturnValueHandlerComposite();
        composite.addHandler(new ModelAndViewMethodReturnValueHandler());
        composite.addHandler(new ViewNameMethodReturnValueHandler());
        composite.addHandler(new ServletModelAttributeMethodProcessor(false));
        composite.addHandler(new HttpEntityMethodProcessor(List.of(new MappingJackson2HttpMessageConverter())));
        composite.addHandler(new HttpHeadersReturnValueHandler());
        composite.addHandler(new RequestResponseBodyMethodProcessor(List.of(new MappingJackson2HttpMessageConverter())));
        composite.addHandler(new ServletModelAttributeMethodProcessor(true));
        return  composite;
    }
}
